/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						script_player_boolean_expression.cpp

	$Header: /heroes4/script_player_boolean_expression.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "script_player_boolean_expression.h"

#include "adventure_map.h"
#include "army.h"
#include "army_array.h"
#include "player.h"
#include "player_color.h"
#include "script_targeting.h"
#include "sized_int_types.h"
#include "streambuf_operators.h"
#include "town.h"
#include "town_type.h"

t_script_player_boolean_expression::t_result 
t_script_player_boolean_expression::evaluate(t_expression_context_hero const& context) const
{
	assert(context.map);
	t_player const* player = select_player_by_target(get_target(), context.map, NULL, context.army_owner, context.opposing_army_owner);
	return do_evaluate(context.map, player);
}

t_script_player_boolean_expression::t_result 
t_script_player_boolean_expression::evaluate(t_expression_context_town const& context) const
{
	assert(context.map);
	t_player const* player = select_player_by_target(get_target(), context.map, context.object, context.garrison ? context.garrison->get_owner() : NULL, context.opposing_army_owner);
	return do_evaluate(context.map, player);
}

t_script_player_boolean_expression::t_result 
t_script_player_boolean_expression::evaluate(t_expression_context_object const& context) const
{
	assert(context.map);
	t_player const* player = select_player_by_target(get_target(), context.map, NULL, NULL, NULL);
	return do_evaluate(context.map, player);
}

t_script_player_boolean_expression::t_result 
t_script_player_boolean_expression::evaluate(t_expression_context_army const& context) const
{
	assert(context.map);
	t_player const* player = select_player_by_target(get_target(), context.map, NULL, context.army_owner, context.opposing_army_owner);
	return do_evaluate(context.map, player);
}

t_script_player_boolean_expression::t_result 
t_script_player_boolean_expression::evaluate(t_expression_context_global const& context) const
{
	assert(context.map);
	t_player const* player = select_player_by_target(get_target(), context.map, NULL, NULL, NULL);
	return do_evaluate(context.map, player);
}

// --------------------------------------------------------------------------
// t_script_player_is_computer members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_script_player_is_computer::t_result
t_script_player_is_computer::do_evaluate( t_adventure_map const* map, t_player const* player ) const
{
	if (player == NULL) return false;
	
	return player->is_computer();
}

// --------------------------------------------------------------------------
// t_script_player_is_human members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_script_player_is_human::t_result
t_script_player_is_human::do_evaluate( t_adventure_map const* map, t_player const* player ) const
{
	if (player == NULL) return false;

	return !player->is_computer();
}

// --------------------------------------------------------------------------
// t_script_player_is_eliminated members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_script_player_is_eliminated::t_result
t_script_player_is_eliminated::do_evaluate( t_adventure_map const* map, t_player const* player ) const
{
	if (player == NULL) return false;
	
	return player->is_eliminated();
}

// --------------------------------------------------------------------------
// t_script_player_is_alignment members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_script_player_is_alignment::t_result
t_script_player_is_alignment::do_evaluate( t_adventure_map const* map, t_player const* player ) const
{
	if (player == NULL) return false;

	return (player->get_alignment() == get_alignment());
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_is_alignment::read_from_map(
	std::streambuf &	stream,
	int					format_version )
{
	if ( !t_script_player_boolean_expression::read_from_map( stream, format_version ) )
		return false;

	m_alignment = t_alignment( get< t_uint8 >( stream ) );
	return m_alignment >= 0 && m_alignment < k_town_type_count;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_is_alignment::read(
	std::streambuf &	stream,
	int					format_version )
{
	if ( !t_script_player_boolean_expression::read( stream, format_version ) )
		return false;

	m_alignment = get< t_alignment >( stream );
	return m_alignment >= 0 && m_alignment < k_town_type_count;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_is_alignment::write( std::streambuf &	stream) const
{
	if ( !t_script_player_boolean_expression::write( stream ) )
		return false;

	put< t_alignment >( stream, m_alignment );
	
	return true;
}

// --------------------------------------------------------------------------
// t_script_player_is_color members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_script_player_is_color::t_result
t_script_player_is_color::do_evaluate( t_adventure_map const* map, t_player const* player ) const 
{
	if (player == NULL) return false;

	return (player->get_color() == get_color());
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_is_color::read_from_map(
	std::streambuf &	stream,
	int					format_version )
{
	if ( !t_script_player_boolean_expression::read_from_map( stream, format_version ) )
		return false;

	m_color = t_player_color( get< t_uint8 >( stream ) );
	return m_color >= 0 && m_color < k_player_color_count;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_is_color::read(
	std::streambuf &	stream,
	int					format_version )
{
	if ( !t_script_player_boolean_expression::read( stream, format_version ) )
		return false;

	m_color = get< t_player_color >( stream );
	return m_color >= 0 && m_color < k_player_color_count;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_is_color::write( std::streambuf &	stream ) const
{
	if ( !t_script_player_boolean_expression::write( stream ) )
		return false;

	put< t_player_color >( stream, m_color );
	
	return true;
}

// --------------------------------------------------------------------------
// t_script_player_owns_hero members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_script_player_owns_hero::t_result
t_script_player_owns_hero::do_evaluate( t_adventure_map const* map, t_player const* player ) const
{
	if (player == NULL) 
		return false;

	t_hero const* hero = map->get_mapped_hero( m_hero_name );

	if (!hero) 
		return false;

	t_army_array const* armies = player->get_armies();
	if (!armies) 
		return false;

	int count = armies->size();
	for (int i = 0; i < count; i++) 
	{
		t_army* army = (*armies)[i].get();
		if (army == NULL) continue;
		t_creature_array const& array = army->get_creatures();
		for (int j = 0; j < t_creature_array::k_size; j++) 
			if (array[j].get_hero() == hero) 
				return true;
	}

	return false;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_owns_hero::read_from_map(
	std::streambuf &	stream,
	int					format_version )
{
	return		t_script_player_boolean_expression::read_from_map( stream, format_version )
			&&	read_string16( stream, m_hero_name );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_owns_hero::read(
	std::streambuf &	stream,
	int					format_version )
{
	if (!t_script_player_boolean_expression::read( stream, format_version )) 
		return false;

	return read_string16( stream, m_hero_name );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_owns_hero::write( std::streambuf &	stream ) const
{
	if (!t_script_player_boolean_expression::write( stream )) 
		return false;

	return write_string16( stream, m_hero_name );
}


// --------------------------------------------------------------------------
// t_script_player_owns_town members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_script_player_owns_town::t_result
t_script_player_owns_town::do_evaluate( t_adventure_map const* map, t_player const* player ) const
{
	if (player == NULL) 
		return false;

	t_town const* town = map->get_mapped_town( m_town_name );

	return town ? (town->get_owner() == player) : false;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_owns_town::read_from_map(
	std::streambuf &	stream,
	int					format_version )
{
	return		t_script_player_boolean_expression::read_from_map( stream, format_version )
			&&	read_string16( stream, m_town_name );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_owns_town::read(
	std::streambuf &	stream,
	int					format_version )
{
	if (!t_script_player_boolean_expression::read( stream, format_version )) 
		return false;

	return read_string16( stream, m_town_name );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_script_player_owns_town::write( std::streambuf &	stream ) const
{
	if (!t_script_player_boolean_expression::write( stream )) 
		return false;

	return write_string16( stream, m_town_name );
}

